home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / NCSA / tn3270 2.4d7 source / tn3270 / writesf.c < prev    next >
Text File  |  1992-04-17  |  43KB  |  1,518 lines

  1. /*
  2.  *  tn3270 for the Macintosh Source Code
  3.  *  Brown University Computing and Information Services
  4.  *  Version 2.4d7  April, 1992
  5.  *  Copyright (c) 1988, 1989, 1990, 1991, 1992 by Brown University and by
  6.  *  Peter John DiCamillo.
  7.  *
  8.  *  Permission is granted to any individual or institution to use, copy,
  9.  *  or redistribute the binary version of this software and its
  10.  *  documentation provided this notice and the copyright notices are
  11.  *  retained.  Permission is granted to any individual or non-profit
  12.  *  institution to use, copy, modify, or redistribute the source files
  13.  *  of this software provided this notice and the copyright notices are
  14.  *  retained.  This software may not be distributed for profit, either
  15.  *  in original form or in derivative works, nor can the source be
  16.  *  distributed to other than an individual or a non-profit institution.
  17.  *  Any  individual or group interested in seeing and/or using these
  18.  *  source files but who are prevented from doing so by the above
  19.  *  constraints should contact Don Wolfe, Assistant Vice-President for
  20.  *  Computer Systems at Brown University, (401) 863-7250, for possible
  21.  *  software licensing of the source developed at Brown.
  22.  *
  23.  *  Brown University and Peter John DiCamillo make no representations
  24.  *  about the suitability of this software for any purpose.
  25.  *
  26.  *  BROWN UNIVERSITY AND PETER JOHN DICAMILLO GIVE NO WARRANTY, EITHER
  27.  *  EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION PROVIDED,
  28.  *  INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY AND
  29.  *  WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
  30.  *
  31.  */
  32.  
  33. /* Code in this file supports WSF functions: Query Reply,
  34.    normal 3270 data (calls writetm), file transfer (calls
  35.    vmxfer), and 3179 graphics.                                */
  36.  
  37. /* Reference manuals for graphics support:
  38.    IBM 3179 G Color Graphics Display Station Description,
  39.    GA18-2261
  40.    Reference Information for Picture Interchange Format,
  41.    SC33-0244  (part of IBM 3270 PC/G or PC/GX library)    
  42.  
  43.    General 3270 data stream information:
  44.    IBM 3270 Information Display System Data Stream
  45.    Programmer's Reference, GA23-0059 (revision -3 includes
  46.    some 3179 information)                                    */
  47.  
  48. /* Graphics has been tested using SAS version 5.16 with
  49.    device names of IBM3179 (SAS built-in support) and
  50.    GDDMPCGX (SAS calling GDDM Release 4).  Test plots include
  51.    the output from the GTESTIT procedure, the "cowboy hat"
  52.    sample, and the BITNET topology maps.                    */
  53.  
  54. #if !defined(USEDUMP)
  55.     #include "maclib.h"
  56.     #include "termdef.h"
  57.     #include "tn3270funcs.h"
  58.     #include "globals.h"
  59. #else
  60.     #pragma load "tn3270DumpFile"
  61. #endif
  62.  
  63. #pragma segment 3270wsf
  64.  
  65. #define    IAC    255        /* interpret as command: */
  66. #define EOR 239     /* end of record (transparent mode) */
  67.  
  68. #define adMax 37    /* Color QuickDraw arithmetic drawing max mode */
  69. #define adMin 39    /* Color QuickDraw arithmetic drawing min mode */
  70.  
  71.                             /* MacDraw PicComment codes we use */
  72. #define picDwgBeg        130
  73. #define picDwgEnd        131
  74. #define picGrpBeg        140
  75. #define picGrpEnd        141
  76.                             /* LaserWriter PicComment codes we use */
  77. #define SetLineWidth    182
  78.  
  79. extern struct Point sfppoint;
  80. extern RGBColor realblack, realwhite;
  81.  
  82. /* Code labelled "temp" is included to allow writing debugging data for
  83.    graphics support to a file.  Writing to the file is suppressed unless
  84.    "cf_dblevel" has been set by the main program.                            */
  85.  
  86. /*temp*/
  87. #include "stdio.h"
  88.  
  89.                             /* write structured field */
  90. void writesf(unsigned char *cmd,    /* command, starting with WSF op-code */
  91.              short len,                /* command length */
  92.              char init,                /* false = data continued from last call */
  93.              cnr *cp)
  94. {
  95. short currlen, curroff, fieldlen;
  96. unsigned char fieldid;
  97. char readflg;
  98.  
  99. if (!init) return;            /* currently, must get all data in one call */
  100. if (len < 1) return;
  101.  
  102. currlen = len - 1;            /* skip over wsf op-code */
  103. curroff = 1;
  104. while (currlen >= 3) {
  105.     fieldlen = cmd[curroff+1] + (cmd[curroff] << 8);
  106.     if (fieldlen == 0) fieldlen = currlen;
  107.     fieldid = cmd[curroff+2];
  108.     readflg = 0;
  109.     intwsf(fieldid, fieldlen, cmd+curroff, &readflg, cp);
  110.     if (readflg) break;        /* command was a read of some sort */
  111.     curroff += fieldlen;
  112.     currlen -= fieldlen;
  113.     }
  114. }
  115.  
  116.                              /* interpret one wsf field */
  117. void intwsf(unsigned char id,        /* wsf field type code */
  118.             short len,                /* length of data */
  119.             unsigned char *data,    /* data, starting with 2-byte length */
  120.             char *rdflag,            /* return 1 if read which generates response */
  121.             cnr *cp)
  122. /* temp */
  123. cp->wsfdbg.wsf_op = id;
  124. cp->wsfdbg.wsf_gr = cp->wsfdbg.grf_op = 0;
  125.  
  126. switch(id) {
  127.  
  128.     case 0x01:                        /* read partition */
  129.                 if (len < 5) break;
  130.                 if ((data[4] == 0x02) || (data[4] == 0x03))
  131.                     if (data[3] == 0xff) 
  132.                         wsfrpq(len, data, cp->newserver && (cp->cs.ext3270 == 0), cp);
  133.                 (*rdflag) = 1;
  134.                 break;
  135.  
  136.     case 0x03:                        /* erase/reset */
  137.                 if (data[3] & 0x80) {
  138.                     cp->ewamode = 1;        /* establish alternate screen size */
  139.                     }
  140.                 else {
  141.                     cp->ewamode = 0;        /* establish default screen size */
  142.                     }
  143.                 newmode(cp->ewamode, 0, cp);
  144.                 clrscn(cp);                /* clear text */
  145.                 cp->drawpict = 1;        /* force graphics clear */
  146.                 clrpict(cp);            /* clear graphics */
  147.                 break;
  148.  
  149.     case 0x06:                        /* load PS set */
  150.                 /* ignore command to clear PS storage */
  151.                 if ((len == 7) && (data[3] & 0x40)) break;
  152.                 /* real PS load not supported */
  153.                 hexdump(data, len, cp); /*temp*/
  154.                 break;
  155.  
  156.     case 0x09:                        /* set reply mode */
  157.                 /* not supported */
  158.                 hexdump(data, len, cp); /*temp*/
  159.                 break;
  160.  
  161.     case 0x0c:                        /* create partition */
  162.                 /* not supported */
  163.                 hexdump(data, len, cp); /*temp*/
  164.                 break;
  165.  
  166.     case 0x0f:                        /* graphic something */
  167.                 if (cp->myWindow == 0) break;
  168.                 writegf(data, len, cp);
  169.                 break;
  170.  
  171.     case 0x20:                        /* file transfer */
  172.                 /* special field type made up for RMAC/WMAC transfer */
  173.                 if (len < 4) break;    /* at least one data byte */
  174.                 cp->rbuf = data+3;
  175.                 cp->rlen = len-3;
  176.                 cp->sbuf = cp->readbuff+6;
  177.                 vmxfer(cp);        /* process file transfer command */
  178.                 if (cp->slen == 0) break;    /* send response, if generated */
  179.                 (cp->readbuff)[0] = 0xd7;
  180.                 cp->slen += 1;
  181.                 (cp->readbuff)[5] = 0x88;
  182.                 cp->rbsize = cp->slen + 5;
  183.                 if (cp->tcpflg) {
  184.                     (cp->readbuff)[cp->rbsize++] = IAC;
  185.                     (cp->readbuff)[cp->rbsize++] = EOR;
  186.                     }
  187.                 senddata(1, cp);
  188.                 break;
  189.  
  190.     case 0x40:                        /* outbound 3270DS */
  191.                 if (len < 5) return;
  192.                 if (data[4] == 0x6f) {            /* EAU */
  193.                     funckey(10, 0, cp);            /* simulate CLEAR key pressed */
  194.                     cp->rdaid = 0x60;
  195.                     break;
  196.                     }
  197.                 if ((data[3] == 0) && (data[4] == 0xf5)) {
  198.                     cp->skipnewmode = 1;        /* EW with PID = 0 keeps mode */
  199.                     }
  200.                 cp->ldvoff = 0;                    /* normal 3270 data stream */
  201.                 writetm(data+4, len-4, 1, cp);    /* update 3270 buffers */
  202.                 cp->skipnewmode = 0;            /* reset special flag */
  203.                 invldscr(cp);                    /* display new contents */
  204.                 endwcc(cp);                        /* post-write WCC functions */
  205.                 break;
  206.     default:
  207.                 hexdump(data, len, cp); /*temp*/
  208.                 break;
  209.     }
  210. }
  211.                             /* Read Partition Query */ 
  212. void wsfrpq(short len, unsigned char *data, char shortrsp, cnr *cp)
  213. {
  214. short i, j, listlen, reqtype, t, typecount, wsflen;
  215. static unsigned char long_wsftypes[] = {    /* all WSFR resources */    
  216.     0x86, 0x87, 0x85, 0x81, 0xa6, 0x88, 0x80, 0x84, 0x96, 0x99,
  217.     0xa1, 0xa8, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb6, 0x00};
  218. static unsigned char long_wsflist[] = {     /* 0x01 if in default list */
  219.     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01,
  220.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  221. static unsigned char short_wsftypes[] = {    /* all WSFR resources */    
  222.     0x85, 0x81, 0xa6, 0x80, 0xa1, 0x00};
  223. static unsigned char short_wsflist[] = {     /* 0x01 if in default list */
  224.     0x01, 0x01, 0x01, 0x01, 0x00};
  225. unsigned char *wsftypes, *wsflist;
  226.  
  227. if (shortrsp) {
  228.     wsftypes = short_wsftypes;
  229.     wsflist = short_wsflist;
  230.     }
  231. else {
  232.     wsftypes = long_wsftypes;
  233.     wsflist = long_wsflist;
  234.     }
  235.  
  236. switch (data[4]) {
  237.     case 0x02:                /* Query */
  238.             listlen = 0;
  239.             reqtype = 1;
  240.             break;
  241.     case 0x03:                /* Query List */
  242.             if (len < 6) return;
  243.             listlen = len - 6;
  244.             reqtype = (data[5] & 0xc0) >> 6;
  245.             if (reqtype == 3) return;
  246.             break;
  247.     default:
  248.             return;
  249.     }
  250. typecount = strlen(wsftypes);
  251. wsflen = 0;
  252. for (i=0; i < typecount; i++) {        /* loop through all possible responses;
  253.                                        include in response those requested */
  254.     t = wsftypes[i];                /* t = resource number */
  255.     if (reqtype == 2) {        /* all types */
  256.         wsfadd(t, &wsflen, shortrsp, cp);
  257.         if (t == 179) wsfadd(254, &wsflen, shortrsp, cp); /* 2nd port response */
  258.         continue;
  259.         }
  260.     if ((reqtype == 1) && (wsflist[i] != 0)) {  /* default types wanted */
  261.         wsfadd(t, &wsflen, shortrsp, cp);
  262.         if (t == 179) wsfadd(254, &wsflen, shortrsp, cp); /* 2nd port response */
  263.         continue;
  264.         }
  265.     if (listlen == 0) continue;        /* listed types wanted */
  266.     for (j=0; j < listlen; j++)
  267.         if (data[j+6] == t) {
  268.             wsfadd(t, &wsflen, shortrsp, cp);
  269.             if (t == 179) wsfadd(254, &wsflen, shortrsp, cp); /* 2nd port response */
  270.             break;
  271.             }
  272.     }
  273.                             /* return null response if no other */
  274. if (wsflen == 0) wsfadd(255, &wsflen, shortrsp, cp);    
  275. (cp->readbuff)[0] = 0xd7;    /* send the response, similarly to read modified */
  276. wsflen += 1;
  277. (cp->readbuff)[5] = 0x88;            /* AID code = 0x88 (structured field) */
  278. cp->rbsize = wsflen + 5;
  279. if (cp->tcpflg) {
  280.     cp->readbuff[cp->rbsize++] = IAC;
  281.     cp->readbuff[cp->rbsize++] = EOR;
  282.     }
  283. senddata(1, cp);
  284. }
  285.  
  286.                          /* add resource no. "num" to response */
  287. void wsfadd(short num, short *len, char shortrsp, cnr *cp)
  288. {
  289. unsigned char **rhandle;
  290. short rlen, rnum;
  291. void (*procptr)(void *resptr, cnr *cp);
  292. unsigned char rscbuff[64];
  293.  
  294. rnum = num;        /* default resource is argument */
  295.  
  296. switch(num) {
  297.     case 129:    procptr = def_ua;        /* usable area */
  298.                 break;
  299.     case 166:    procptr = def_ip;        /* implicit partition */
  300.                 break;
  301.     default:    procptr = 0;
  302.                 break;
  303.     }
  304.  
  305. if (cp->cs.altptsize == 12) {
  306.     switch(num) {
  307.         case 133:    rnum = 252;            /* character sets */
  308.                     break;
  309.         case 182:    rnum = 250;            /* graphic symbol sets */
  310.                     break;
  311.         default:    break;
  312.         }
  313.     }
  314.  
  315. if (colormac && (!cp->cs.nocolor)) if (num == 134) rnum = 245;
  316. if (shortrsp) if (num == 128) rnum = 244;
  317.  
  318. if (cp->cs.simps) {                    /* include PS character set response */
  319.     if (rnum == 133) rnum = 251;
  320.     if (rnum == 252) rnum = 253;
  321.     }
  322.  
  323. rhandle = (unsigned char **)GetResource('WSFR', rnum);
  324. if (rhandle == 0) return;    /* should report error here */
  325. rlen = ((*rhandle)[0] << 8) + (*rhandle)[1];
  326.                     /* modify response which depends on screen format */
  327. if (procptr != 0) {
  328.     memcpy(rscbuff, (*rhandle), rlen);
  329.     (*procptr)(rscbuff, cp);
  330.     tcpmemcpy(cp->readbuff+6+(*len), rscbuff, &rlen, cp->tcpflg);
  331.     }
  332. else {
  333.     tcpmemcpy(cp->readbuff+6+(*len), (*rhandle), &rlen, cp->tcpflg);
  334.     }
  335. (*len) += rlen;
  336. }
  337.  
  338.                     /* modify usable area response for screen format */
  339. void def_ua(uareply *resptr, cnr *cp)
  340. {
  341. union {
  342.     unsigned short i;
  343.     unsigned char s[2];
  344.     } cvt;
  345.  
  346. resptr->w = 80;
  347. resptr->h = 24;
  348. switch (cp->cs.dfltptsize) {
  349.     case 12:
  350.             resptr->aw = 7;
  351.             resptr->ah = 16;
  352.             break;
  353.     default:
  354.             resptr->aw = 6;
  355.             resptr->ah = 12;
  356.             break;
  357.     }
  358.  
  359. cvt.i = cp->cs.altcols;
  360. memcpy(resptr->waua, cvt.s, 2);
  361. cvt.i = cp->cs.altrows;
  362. memcpy(resptr->haua, cvt.s, 2);
  363. switch (cp->cs.altptsize) {
  364.     case 12:
  365.             resptr->awaua = 7;
  366.             resptr->ahaua = 16;
  367.             break;
  368.     default:
  369.             resptr->awaua = 6;
  370.             resptr->ahaua = 12;
  371.             break;
  372.     }
  373. }
  374.     
  375.                     /* modify implicit partition response for screen format */
  376. void def_ip(ipreply *resptr, cnr *cp)
  377. {
  378. union {
  379.     unsigned short i;
  380.     unsigned char s[2];
  381.     } cvt;
  382.  
  383. cvt.i = 80;
  384. memcpy(resptr->wd, cvt.s, 2);
  385. cvt.i = 24;
  386. memcpy(resptr->hd, cvt.s, 2);
  387. cvt.i = cp->cs.altcols;
  388. memcpy(resptr->wa, cvt.s, 2);
  389. cvt.i = cp->cs.altrows;
  390. memcpy(resptr->ha, cvt.s, 2);
  391. switch (cp->cs.dfltptsize) {
  392.     case 12:
  393.             cvt.i = 7;
  394.             memcpy(resptr->wcd, cvt.s, 2);
  395.             cvt.i = 16;
  396.             memcpy(resptr->hcd, cvt.s, 2);
  397.             break;
  398.     default:
  399.             cvt.i = 6;
  400.             memcpy(resptr->wcd, cvt.s, 2);
  401.             cvt.i = 12;
  402.             memcpy(resptr->hcd, cvt.s, 2);
  403.             break;
  404.     }
  405. switch (cp->cs.altptsize) {
  406.     case 12:
  407.             cvt.i = 7;
  408.             memcpy(resptr->wca, cvt.s, 2);
  409.             cvt.i = 16;
  410.             memcpy(resptr->hca, cvt.s, 2);
  411.             break;
  412.     default:
  413.             cvt.i = 6;
  414.             memcpy(resptr->wca, cvt.s, 2);
  415.             cvt.i = 12;
  416.             memcpy(resptr->hca, cvt.s, 2);
  417.             break;
  418.     }
  419. }
  420.     
  421. void writegf(unsigned char *data, short len, cnr *cp)    /* graphic data stream */
  422. {
  423. short i;
  424.  
  425. cp->wsfdbg.wsf_gr = data[3];        /*temp*/
  426.  
  427. pictcp = cp;                        /* for saving graphics */
  428.  
  429. switch(data[3]) {
  430.     case 0x0f:                            /* graphic data */
  431.                 /* not supported */        /* controls inbound graphics data */
  432.                 hexdump(data+7, len-7, cp); /*temp*/
  433.                 break;
  434.     case 0x10:                            /* graphic picture */
  435.                 if (data[5] & 0x80) {
  436.                     cp->pleft = 0;                /* if first, reset count */
  437.                     initpict(cp);                /* maybe start of new picture */
  438.                     }
  439.                 if (len < 8) break;
  440.                 for (i=7; i < len; i++) grpparse(data[i], cp);
  441.                 if (data[5] & 0x40) showpict(cp);    /* if last, show result */
  442.                 break;
  443.     case 0x11:                            /* graphic control */
  444.                 if (data[5] & 0x80) {
  445.                     cp->cleft = 0;                /* if first, reset count */
  446.                     initpict(cp);                /* maybe start of new picture */
  447.                     }
  448.                 if (len < 8) break;
  449.                 for (i=7; i < len; i++) grcparse(data[i], cp);
  450.                 if (data[5] & 0x40) showpict(cp);    /* if last, show result */
  451.                 break;
  452.     case 0x1f:                            /* OEM data */
  453.                 /* not supported */
  454.                 hexdump(data+7, len-7, cp); /*temp*/
  455.                 break;
  456.  
  457.     default:    hexdump(data+7, len-7, cp);    /*temp*/
  458.                 break;
  459.     }
  460. }
  461.  
  462. void grpparse(unsigned char c, cnr *cp)        /* interpret graphic picture data */
  463. if (cp->pleft == 0) {
  464.     cp->pmode = cp->pcount = 0;
  465.     cp->pleft = 14;
  466.     }
  467.  
  468. switch (cp->pmode) {
  469.     case 0:                    /* processing segment header */
  470.             if (cp->pcount == 8) cp->ptemp1 = c;
  471.             if (cp->pcount == 9) cp->pleft = (cp->ptemp1 << 8) + c + 5;
  472.             if (cp->pcount == 13) {
  473.                     cp->pmode = 1;
  474.                     cp->pcount = 0;
  475.                     }
  476.             else cp->pcount++;
  477.             break;
  478.     case 1:                    /* processing order */
  479.             if (cp->pcount == 0) {
  480.                 cp->pboff = 0;
  481.                 (cp->pictbuff)[cp->pboff++] = c;
  482.                 if ((c==0x00) || (c==0x20) || (c==0xff)) {
  483.                     exdraw(cp->pictbuff, cp->pboff, cp);
  484.                     cp->pcount = 0;
  485.                     }
  486.                 else cp->pcount++;
  487.                 break;
  488.                 }
  489.             (cp->pictbuff)[cp->pboff++] = c;
  490.             if (cp->pcount == 1) {
  491.                 if ((((cp->pictbuff)[0] <= 0x7f) &&
  492.                       (((cp->pictbuff)[0] & 0x0f) >= 8)) || (c == 0)) {
  493.                     exdraw(cp->pictbuff, cp->pboff, cp);
  494.                     cp->pcount = 0;
  495.                     }
  496.                 else {
  497.                     cp->ptemp1 = c;        /* no. of operand bytes left */
  498.                     cp->pcount++;
  499.                     }
  500.                 break;
  501.                 }
  502.             cp->pcount++;
  503.             cp->ptemp1--;
  504.             if (cp->ptemp1 == 0) {
  505.                 exdraw(cp->pictbuff, cp->pboff, cp);
  506.                 cp->pcount = 0;
  507.                 }
  508.             break;
  509.     default:
  510.             break;
  511.     }
  512. cp->pleft--;
  513. }
  514.  
  515. void exdraw(unsigned char *opdata, short len, cnr *cp)    /* process drawing order */
  516. {
  517. short r, s;
  518. union {
  519.     short ipos;
  520.     unsigned char cpos[2];
  521.     } cvt;
  522. GrafPtr gp, dp;
  523. short newcolor;
  524. RGBColor rgbtemp;
  525. unsigned char imagebuff[258];
  526. unsigned char * imageptr;
  527. short imgoffset;
  528.  
  529. GetPort(&gp);
  530. if (cp->PictPtr != 0) {
  531.     SetPort(cp->PictPtr);
  532.     setgdev(cp);
  533.     }
  534. else {
  535.     SetPort(cp->myWindow);
  536.     }
  537. GetPort(&dp);
  538.  
  539. if (cf_dblevel == 3) {                /* dump all graphics if level 3 */
  540.     cp->wsfdbg.grf_op = opdata[0];    /* temp */
  541.     hexdump(opdata, len, cp);        /* temp */
  542.     }
  543.  
  544. switch(opdata[0]) {
  545.         case 0xa1:                    /* rel. line at current pos. */
  546.             r = opdata[1]/2;
  547.             s = 2;
  548.             MoveTo(sx(cp->xpos, cp), sy(cp->ypos, cp));
  549.             while (r > 0) {    
  550.                 cp->xpos += (char)opdata[s++];
  551.                 cp->ypos += (char)opdata[s++];
  552.                 myLineTo(sx(cp->xpos, cp), sy(cp->ypos, cp), cp);
  553.                 r --;
  554.                 }
  555.             break;
  556.         case 0x21:                    /* set current position */
  557.             cvt.cpos[0] = opdata[2];
  558.             cvt.cpos[1] = opdata[3];
  559.             cp->xpos = cvt.ipos;
  560.             cvt.cpos[0] = opdata[4];
  561.             cvt.cpos[1] = opdata[5];
  562.             cp->ypos = cvt.ipos;
  563.             break;
  564.         case 0x83:                    /* char. string at curr. pos. */
  565.             MoveTo(sx(cp->xpos, cp), sy(cp->ypos, cp)-2);
  566.             myDrawString(opdata+1, cp);
  567.             break;
  568.         case 0xc3:                    /* char. string at given pos. */
  569.             cvt.cpos[0] = opdata[2];
  570.             cvt.cpos[1] = opdata[3];
  571.             cp->xpos = cvt.ipos;
  572.             cvt.cpos[0] = opdata[4];
  573.             cvt.cpos[1] = opdata[5];
  574.             cp->ypos = cvt.ipos;
  575.             MoveTo(sx(cp->xpos, cp), sy(cp->ypos, cp));
  576.             opdata[5] = opdata[1] - 4;
  577.             if (opdata[5] < 0) opdata[5] = 0;
  578.             myDrawString(opdata+5, cp);
  579.             break;
  580.         case 0x85:                    /* fillet at current position */
  581.                 /* see comment below for fillet at given position */
  582.         case 0x81:                    /* line at current position */
  583.             r = opdata[1]/4;
  584.             s = 2;
  585.             MoveTo(sx(cp->xpos, cp), sy(cp->ypos, cp));
  586.             while (r > 0) {    
  587.                 cvt.cpos[0] = opdata[s++];
  588.                 cvt.cpos[1] = opdata[s++];
  589.                 cp->xpos = cvt.ipos;
  590.                 cvt.cpos[0] = opdata[s++];
  591.                 cvt.cpos[1] = opdata[s++];
  592.                 cp->ypos = cvt.ipos;
  593.                 myLineTo(sx(cp->xpos, cp), sy(cp->ypos, cp), cp);
  594.                 r --;
  595.                 }
  596.             break;
  597.         case 0xc5:                    /* fillet at given position */
  598.                 /* Too hard to do correctly for now, but at least    */
  599.                 /* draw the lines the curve should be tangent to,    */
  600.                 /* and update the current position.  Fillet has        */
  601.                 /* not been encountered in any test plots.            */
  602.         case 0xc1:                    /* line at given position */
  603.             cvt.cpos[0] = opdata[2];
  604.             cvt.cpos[1] = opdata[3];
  605.             cp->xpos = cvt.ipos;
  606.             cvt.cpos[0] = opdata[4];
  607.             cvt.cpos[1] = opdata[5];
  608.             cp->ypos = cvt.ipos;
  609.             MoveTo(sx(cp->xpos, cp), sy(cp->ypos, cp));
  610.             r = (opdata[1]-4)/4;
  611.             s = 6;
  612.             while (r > 0) {    
  613.                 cvt.cpos[0] = opdata[s++];
  614.                 cvt.cpos[1] = opdata[s++];
  615.                 cp->xpos = cvt.ipos;
  616.                 cvt.cpos[0] = opdata[s++];
  617.                 cvt.cpos[1] = opdata[s++];
  618.                 cp->ypos = cvt.ipos;
  619.                 myLineTo(sx(cp->xpos, cp), sy(cp->ypos, cp), cp);
  620.                 r --;
  621.                 }
  622.             break;
  623.         case 0xe1:                    /* relative line at given pos. */
  624.             cvt.cpos[0] = opdata[2];
  625.             cvt.cpos[1] = opdata[3];
  626.             cp->xpos = cvt.ipos;
  627.             cvt.cpos[0] = opdata[4];
  628.             cvt.cpos[1] = opdata[5];
  629.             cp->ypos = cvt.ipos;
  630.             MoveTo(sx(cp->xpos, cp), sy(cp->ypos, cp));
  631.             r = (opdata[1]-4)/2;
  632.             s = 6;
  633.             while (r > 0) {    
  634.                 cp->xpos += (char)opdata[s++];
  635.                 cp->ypos += (char)opdata[s++];
  636.                 myLineTo(sx(cp->xpos, cp), sy(cp->ypos, cp), cp);
  637.                 r --;
  638.                 }
  639.             break;
  640.         case 0xc7:                /* full arc at given position */
  641.                 /* Arcs are not supported yet, but at least move to    */
  642.                 /* the specified position.  Arc commands have not    */
  643.                 /* been encountered in any test plots.                */
  644.             cvt.cpos[0] = opdata[2];
  645.             cvt.cpos[1] = opdata[3];
  646.             cp->xpos = cvt.ipos;
  647.             cvt.cpos[0] = opdata[4];
  648.             cvt.cpos[1] = opdata[5];
  649.             cp->ypos = cvt.ipos;
  650.             break;
  651.         case 0x87:                /* full arc at current position */
  652.                 /* doesn't affect current position */
  653.         case 0x22:                /* set arc parameters */
  654.             break;
  655.         case 0x26:                /* set extended color */
  656.             setrgb(&newcolor, opdata[3], cp);
  657.             if (colormac && (!cp->cs.nocolor)) {
  658.                 GetEntryColor(cp->myPalette, newcolor, &rgbtemp);
  659.                 RGBForeColor(&rgbtemp);        /* set foreground drawing color */
  660.                 }
  661.             else {
  662.                 if (newcolor == RGBblack) {
  663.                     ForeColor(whiteColor);
  664.                     }
  665.                 else {
  666.                     ForeColor(blackColor);
  667.                     }
  668.                 }
  669.             break;
  670.         case 0x0a:                /* set color */
  671.             setrgb(&newcolor, opdata[1], cp);
  672.             if (colormac && (!cp->cs.nocolor)) {
  673.                 GetEntryColor(cp->myPalette, newcolor, &rgbtemp);
  674.                 RGBForeColor(&rgbtemp);        /* set foreground drawing color */
  675.                 }
  676.             else {
  677.                 if (newcolor == RGBblack) {
  678.                     ForeColor(whiteColor);
  679.                     }
  680.                 else {
  681.                     ForeColor(blackColor);
  682.                     }
  683.                 }
  684.             break;
  685.         case 0x68:                /* begin area */
  686.             cp->mypoly = OpenPoly();    /* create new polygon */
  687.             cp->aflags = opdata[1];        /* save flag bits */
  688.             cp->area_active = 1;        /* remeber area is active */
  689.             break;
  690.         case 0x60:                /* end area */
  691.             if (cp->area_active == 0) {    /* check for datastream error */
  692.                 break;
  693.                 }
  694.             ClosePoly();            /* done saving stuff */
  695.             PenPat(&(cp->fillpat));        /* set fill pattern */
  696.             PaintPoly(cp->mypoly);        /* draw it */
  697.             PenPat(&qd.black);        /* restore default pattern */
  698.             if (cp->aflags & 0x40) FramePoly(cp->mypoly);  /* handle outline */
  699.             KillPoly(cp->mypoly);        /* dispose of it */
  700.             cp->area_active = 0;        /* reset active flag */
  701.             break;
  702.         case 0x28:                /* set pattern symbol (area fill pattern) */
  703.             setpat(&(cp->fillpat), opdata[1], cp);
  704.             break;
  705.         case 0x29:                /* set marker symbol */
  706.             setmark(&(cp->markchar), opdata[1], cp);
  707.             break;
  708.         case 0xc2:                /* marker at given position */
  709.         case 0x82:                /* marker at current position */
  710.             r = opdata[1]/4;
  711.             s = 2;
  712.             while (r > 0) {    
  713.                 cvt.cpos[0] = opdata[s++];
  714.                 cvt.cpos[1] = opdata[s++];
  715.                 cp->xpos = cvt.ipos;
  716.                 cvt.cpos[0] = opdata[s++];
  717.                 cvt.cpos[1] = opdata[s++];
  718.                 cp->ypos = cvt.ipos;
  719.                 MoveTo(sx(cp->xpos, cp), sy(cp->ypos, cp)+4);
  720.                 (cp->markstr)[1] = cp->markchar;        /* make 1-character Pascal string */
  721.                 myDrawString(cp->markstr, cp);
  722.                 r --;
  723.                 }
  724.             break;
  725.         case 0x18:                /* set line type */
  726.             if (opdata[1] == 0) cp->linet = cp->dfltlt;
  727.             else cp->linet = opdata[1];
  728.             break;
  729.         case 0x19:                /* set line width */
  730.             if (opdata[1] == 0) cp->linew = cp->dfltlw;
  731.             else cp->linew = opdata[1];
  732.             break;
  733.         case 0xd1:                /* begin image */
  734.         case 0x91:                /* begin image at current position */
  735.             cp->image_srcRect.top = 0;
  736.             cp->image_srcRect.left = 0;
  737.             cp->image_srcRect.bottom = 1;
  738.             if (opdata[0] == 0xd1) {
  739.                 /* ignore if not in the format we expect*/
  740.                 if (opdata[1] != 10) break;
  741.                 if (opdata[6] != 0) break;
  742.                 if (opdata[7] != 0) break;
  743.                 /* define upper left corner of bitmap */
  744.                 cvt.cpos[0] = opdata[2];
  745.                 cvt.cpos[1] = opdata[3];
  746.                 cp->image_dstRect.left = sx(cvt.ipos, cp);
  747.                 cvt.cpos[0] = opdata[4];
  748.                 cvt.cpos[1] = opdata[5];
  749.                 cp->image_dstRect.top = sy(cvt.ipos, cp);
  750.                 imgoffset = 8;
  751.                 }
  752.             else {
  753.                 /* ignore if not in the format we expect*/
  754.                 if (opdata[1] != 6) break;
  755.                 if (opdata[2] != 0) break;
  756.                 if (opdata[3] != 0) break;
  757.                 /* define upper left corner of bitmap */
  758.                 cp->image_dstRect.left = sx(cp->xpos, cp);
  759.                 cp->image_dstRect.top = sy(cp->ypos, cp);
  760.                 imgoffset = 4;
  761.                 }
  762.             cp->image_dstRect.bottom = cp->image_dstRect.top + 1;
  763.             /* convert width */
  764.             cvt.cpos[0] = opdata[imgoffset];
  765.             cvt.cpos[1] = opdata[imgoffset+1];
  766.             cp->image_srcRect.right = cvt.ipos;
  767.             cp->image_dstRect.right = cp->image_dstRect.left + cvt.ipos;
  768.             cp->image_srcBits.rowBytes = (cvt.ipos+7)/8;
  769.             if (cp->image_srcBits.rowBytes%2) cp->image_srcBits.rowBytes++;
  770.             /* convert height */
  771.             cvt.cpos[0] = opdata[imgoffset+2];
  772.             cvt.cpos[1] = opdata[imgoffset+3];
  773.             cp->image_rowcount = cvt.ipos;
  774.             cp->image_srcBits.bounds = cp->image_srcRect;
  775.             if (cp->pictopen) {
  776.                 if (cp->image_dstRect.top < cp->ymin) cp->ymin = cp->image_dstRect.top;
  777.                 if (cp->image_dstRect.top > cp->ymax) cp->ymax = cp->image_dstRect.top;
  778.                 if (cp->image_dstRect.bottom < cp->ymin) cp->ymin = cp->image_dstRect.bottom;
  779.                 if (cp->image_dstRect.bottom > cp->ymax) cp->ymax = cp->image_dstRect.bottom;
  780.                 if (cp->image_dstRect.left < cp->xmin) cp->xmin = cp->image_dstRect.left;
  781.                 if (cp->image_dstRect.left > cp->xmax) cp->xmax = cp->image_dstRect.left;
  782.                 if (cp->image_dstRect.right < cp->xmin) cp->xmin = cp->image_dstRect.right;
  783.                 if (cp->image_dstRect.right > cp->xmax) cp->xmax = cp->image_dstRect.right;
  784.                 }
  785.             cp->image_active = 1;
  786.             break;
  787.         case 0x92:                /* image data */
  788.             if (cp->image_active == 0) break;
  789.             if (cp->image_rowcount == 0) break;
  790.             cp->image_rowcount--;
  791.             imageptr = imagebuff;
  792.             if (((long)imageptr)%2) imageptr++;
  793.             memcpy(imageptr, opdata+2, opdata[1]);
  794.             cp->image_srcBits.baseAddr = imageptr;
  795.             if (colormac && (!cp->cs.nocolor)) {
  796.                 GetBackColor(&rgbtemp);
  797.                 if (cp->cs.invertbw) { 
  798.                     RGBBackColor(&realwhite);
  799.                     }
  800.                 else {
  801.                     RGBBackColor(&realblack);
  802.                     }
  803.                 CopyBits(&(cp->image_srcBits), &(dp->portBits),
  804.                     &(cp->image_srcRect), &(cp->image_dstRect), cp->copymode, 0L);
  805.                 RGBBackColor(&rgbtemp);
  806.                 }
  807.             else {
  808.                 CopyBits(&(cp->image_srcBits), &(dp->portBits),
  809.                     &(cp->image_srcRect), &(cp->image_dstRect), cp->copymode, 0L);
  810.                 }
  811.             cp->image_dstRect.top++;
  812.             cp->image_dstRect.bottom++;
  813.             break;
  814.         case 0x93:                /* end image */
  815.             if (cp->image_active == 0) break;
  816.             cp->image_active = 0;
  817.             break;
  818.         case 0x0c:                /* set foreground mix */
  819.             setmixmode(opdata[1], cp);
  820.             break;
  821.         /* The following are not easily implemented using QuickDraw; */
  822.         /* none of these appear to be needed for the test plots to     */
  823.         /* display correctly:                                           */
  824.         case 0x33:                /* set character cell */
  825.         case 0x34:                /* set character angle */
  826.         case 0x35:                /* set character shear */
  827.         case 0x38:                /* set character set */
  828.         case 0x3a:                /* set character direction */
  829.         case 0x37:                /* set marker cell */
  830.         case 0xff:                /* end of symbol definition */
  831.         /* The following are documented by IBM to be ignored in    files    */
  832.         /* imported into GGXA, and are unlikely to be used.  None of    */
  833.         /* of the test plots need them.                                    */
  834.         case 0x0d:                /* set background mix */
  835.             /* no-op for 3179 */
  836.         case 0x39:                /* set character precision */
  837.         case 0x3b:                /* set marker precision */
  838.         case 0x3c:                /* set marker set */
  839.         case 0x08:                /* set pattern set */
  840.         case 0x43:                /* set pick identifier */
  841.         case 0x04:                /* segment characteristics */
  842.         case 0x3e:                /* end prologue */
  843.         case 0x71:                /* end segment */
  844.         /* these do nothing by definition */
  845.         case 0x01:                /* comment */
  846.         case 0x00:                /* no-op */
  847.             break;
  848.         default:
  849.             if (cf_dblevel == 3) break;    /* for level 3, already dumped */
  850.             cp->wsfdbg.grf_op = opdata[0];    /* temp */
  851.             hexdump(opdata, len, cp);        /* temp */
  852.             break;
  853.         }
  854.  
  855. if (cp->PictPtr != 0) resetgdev();
  856. SetPort(gp);
  857. }
  858.  
  859. void grcparse(unsigned char c, cnr *cp)
  860. {
  861. if (cp->cleft == 0) {
  862.     cp->cmode = cp->ccount = 0;
  863.     cp->cleft = 12;
  864.     }
  865.  
  866. switch (cp->cmode) {
  867.     case 0:            /* processing procedure header */
  868.         if (cp->ccount == 8) cp->ctemp1 = c;
  869.         if (cp->ccount == 9) cp->cleft = (cp->ctemp1 << 8) + c + 3;
  870.         if (cp->ccount == 11) {
  871.             cp->cmode = 1;
  872.             cp->ccount = 0;
  873.             }
  874.         else cp->ccount++;
  875.         break;
  876.     case 1:            /* processing procedural instruction */
  877.         if (cp->ccount == 0) {
  878.             cp->cboff = 0;
  879.             (cp->ctlbuff)[cp->cboff++] = c;
  880.             if (c == 0x00) {
  881.                 exctl(cp->ctlbuff, cp->cboff, cp);
  882.                 cp->ccount = 0;
  883.                 }
  884.             else cp->ccount++;
  885.             break;
  886.             }
  887.         (cp->ctlbuff)[cp->cboff++] = c;
  888.         if (cp->ccount == 1) {
  889.             if (((cp->ctlbuff)[0] >= 0x08) && ((cp->ctlbuff)[0] <= 0x0f)) {
  890.                 exctl(cp->ctlbuff, cp->cboff, cp);
  891.                 cp->ccount = 0;
  892.                 }
  893.             else {
  894.                 cp->ctemp1 = c;        /* no. of operand bytes left */
  895.                 cp->ccount++;
  896.                 }
  897.             break;
  898.             }
  899.         cp->ccount++;
  900.         cp->ctemp1--;
  901.         if (cp->ctemp1 == 0) {
  902.             exctl(cp->ctlbuff, cp->cboff, cp);
  903.             cp->ccount = 0;
  904.             }
  905.         break;
  906.     default:
  907.         break;
  908.     }
  909. cp->cleft--;
  910. }
  911.  
  912. void exctl(unsigned char *opdata, short len, cnr *cp)    /* process control command */
  913. {
  914. GrafPtr gp;
  915. char setdflt;
  916. short i;
  917.  
  918. GetPort(&gp);
  919. if (cp->PictPtr != 0) {
  920.     SetPort(cp->PictPtr);
  921.     setgdev(cp);
  922.     }
  923. else SetPort(cp->myWindow);
  924.  
  925. if (cf_dblevel == 3) {            /* for level 3, dump all graphics */
  926.     cp->wsfdbg.grf_op = opdata[0];    /* temp */
  927.     hexdump(opdata, len, cp);        /* temp */
  928.     }
  929.  
  930. switch(opdata[0]) {
  931.     case 0x0a:                    /* erase graphics space */
  932.         clrpict(cp);
  933.         break;
  934.     case 0x00:                    /* no operation */
  935.     case 0x01:                    /* comment */
  936.     case 0x0f:                    /* stop draw */  /* no-op for 3179 */
  937.         break;
  938.     case 0x21:                    /* set current defaults */
  939.                 /* untested- not used by test plots */
  940.         setdflt = (opdata[5] & 0x80) == 0;
  941.         switch(opdata[2]) {            /* SET code */
  942.             case 0x00:                    /* drawing attributes */
  943.                 i = 6;                        /* offset for next data byte */
  944.                 if (opdata[3] & 0x80) {     /* color specified */
  945.                     if (setdflt) cp->dfltcolor = 4;        /* green */
  946.                     else cp->dfltcolor = opdata[i+1];
  947.                     i += 2;
  948.                     }
  949.                 if (opdata[3] & 0x20) {        /* foreground mix specified */
  950.                     if (setdflt) cp->dfltmix = 2;        /* overpaint */
  951.                     else cp->dfltmix = opdata[i];
  952.                     i++;
  953.                     }    
  954.                 break;
  955.             case 0x01:                    /* line attributes */
  956.                 i = 6;                        /* offset for next data byte */
  957.                 if (opdata[3] & 0x80) {        /* line type specified */
  958.                     if (setdflt) cp->dfltlt = 7;    /* default is solid line */
  959.                     else cp->dfltlt = opdata[i];
  960.                     i++;
  961.                     }
  962.                 if (opdata[3] & 0x40)        /* line width specified */
  963.                     if (setdflt) cp->dfltlw = 1;    /* default is 1 pixel wide */
  964.                     else cp->dfltlw = opdata[i];
  965.                 break;
  966.             case 0x02:                    /* character attributes */
  967.                 break;                        /* not supported */
  968.             case 0x03:                    /* marker attributes */
  969.                 i = 6;                        /* offset for next data byte */
  970.                 if (opdata[3] & 0x40)        /* cellsize */
  971.                     i += 4;
  972.                 if (opdata[3] & 0x10)        /* precision */
  973.                     i += 1;
  974.                 if (opdata[3] & 0x08)        /* symbol set */
  975.                     i += 1;
  976.                 if (opdata[3] & 0x01)        /* marker symbol */
  977.                     if (setdflt) cp->dfltmarker = 0xb5;        /* diamond */
  978.                     else setmark(&(cp->dfltmarker), opdata[i], cp);
  979.                 break;
  980.             case 0x04:                    /* pattern attributes */
  981.                 i = 6;                        /* offset for next data byte */
  982.                 if (opdata[3] & 0x08)        /* symbol set */
  983.                     i += 1;
  984.                 if (opdata[3] & 0x01)        /* pattern symbol */
  985.                     if (setdflt) setpat(&(cp->dfltpat), 16, cp);
  986.                     else setpat(&(cp->dfltpat), opdata[i], cp);
  987.                 break;
  988.             case 0x0b:                    /* arc parameters */
  989.                 break;                        /* not supported */
  990.             default:                    /* reserved; SAS & GDDM use 0x05, 0x07 */
  991.                 if (cf_dblevel == 3) break;    /* for level 3, dumped already */        
  992.                 cp->wsfdbg.grf_op = opdata[0];        /* temp */
  993.                 hexdump(opdata, len, cp);            /* temp */
  994.                 break;
  995.             }
  996.         break;
  997.         /* no support for the graphics cursor */
  998.     case 0x08:                    /* attach graphic cursor */
  999.     case 0x09:                    /* detach graphic cursor */
  1000.     case 0x31:                    /* set graphic cursor pos. */
  1001.         break;
  1002.     default:
  1003.         if (cf_dblevel == 3) break;    /* for level 3, dumped already */        
  1004.         cp->wsfdbg.grf_op = opdata[0];        /* temp */
  1005.         hexdump(opdata, len, cp);            /* temp */
  1006.         break;
  1007.     }
  1008.  
  1009. if (cp->PictPtr != 0) resetgdev();
  1010. SetPort(gp);
  1011. }
  1012.  
  1013. void clrpict(cnr *cp)        /* erase graphics space */
  1014. {
  1015. GrafPtr gp;
  1016. RGBColor rgbtemp;
  1017. static unsigned char endarea[] = {0x60, 0};
  1018. static unsigned char endimage[] = {0x93, 0};
  1019.  
  1020. cp->pndclr = 0;                            /* reset pending clear */
  1021. if (cp->drawpict == 0) return;            /* nothing to do if no graphics */
  1022. if (cp->area_active) {                    /* end area if still active */
  1023.     exdraw(endarea, 2, cp);                /* execute end area command */
  1024.     }
  1025. if (cp->image_active) {                    /* end image if still active */
  1026.     exdraw(endimage, 2, cp);            /* execute end image command */
  1027.     }
  1028. if (cp->pictopen) {                        /* close PICT file if open */
  1029.     closepictfile(cp);
  1030.     }
  1031. GetPort(&gp);                        /* save current GrafPort */
  1032. if (cp->PictPtr == 0) {                /* erase port we draw in */
  1033.     SetPort(cp->myWindow);
  1034.     EraseRect(&((cp->myWindow)->portRect));
  1035.     setmixmode(0, cp);                /* set default pen mode */
  1036.     }
  1037. else {
  1038.     SetPort(cp->PictPtr);
  1039.     setgdev(cp);
  1040.     EraseRect(&(cp->PictPort.portRect));
  1041.     setmixmode(0, cp);
  1042.     resetgdev();
  1043.     }
  1044. if (colormac && (!cp->cs.nocolor)) {
  1045.     SetPort(cp->WritePtr);            /* restore background color */
  1046.     if (cp->textmap) setgdev(cp);
  1047.     GetEntryColor(cp->myPalette, RGBback, &rgbtemp);
  1048.     RGBBackColor(&rgbtemp);
  1049.     if (cp->textmap) resetgdev();
  1050.     }
  1051. SetPort(gp);                        /* restore GrafPort */
  1052. cp->drawpict = 0;                    /* don't show graphics any more */
  1053. cp->newpict = 1;                    /* next order starts new picture */
  1054. if (cp->pendalign) {                /* align bitmaps if changed during display */
  1055.     alignbitmaps(cp);
  1056.     newstat(cp);
  1057.     }
  1058. invldscr(cp);                        /* force screen to be redrawn */
  1059.                                     /* end saving PICT file */
  1060. }
  1061.  
  1062. void initpict(cnr *cp)        /* initialize at start of new picture */
  1063. {
  1064. if (!(cp->newpict)) return;
  1065. cp->drawpict = 1;        /* clear initial screen */
  1066. clrpict(cp);            /* (resets drawpict, sets newpict) */
  1067. cp->newpict = 0;        /* no longer new picture */
  1068.                         /* begin saving PICT file */
  1069. if (cp->savepict && (cp->PictPtr != 0)) {
  1070.     openpictfile(cp);
  1071.     }
  1072. }
  1073.  
  1074. void showpict(cnr *cp)        /* cause graphics data to be displayed */
  1075. {
  1076. GrafPtr gp;
  1077. RGBColor rgbtemp;
  1078.  
  1079. cp->drawpict = 1;                    /* include graphics in screen updates */
  1080. if (colormac && (!cp->cs.nocolor)) {                        /* change text background to black or white */
  1081.     GetPort(&gp);
  1082.     SetPort(cp->WritePtr);
  1083.     if (cp->textmap) setgdev(cp);
  1084.     if (cp->cs.invertbw) GetEntryColor(cp->myPalette, RGBwhite, &rgbtemp);
  1085.              else GetEntryColor(cp->myPalette, RGBblack, &rgbtemp);
  1086.     RGBBackColor(&rgbtemp);
  1087.     SetPort(gp);
  1088.     if (cp->textmap) resetgdev();
  1089.     }
  1090. invldscr(cp);                        /* invalidate screen to force update */
  1091. }
  1092.  
  1093. /* The following two function are simple now, since tn3270's response to
  1094.    WSF Query Reply now accurately describes the Mac screen dimensions.    
  1095.    Both SAS and GDDM adapt to this very well.                            */
  1096.  
  1097. short sx(short x, cnr *cp)        /* convert data stream x-coordinate to Mac coordinate */
  1098. {
  1099. register short r;
  1100.  
  1101. /* if (PictPtr == 0) {
  1102.     if (cur_ptsize == 12) r = x + 286;
  1103.     else r = x + 246;
  1104.     }
  1105. else {
  1106.     if (cur_ptsize == 12) r = x + 318;
  1107.     else r = x + 255;
  1108.     }    */
  1109. r = x + cp->hpixsize/2;
  1110. if (cp->PictPtr == 0) {
  1111.     r += cp->textRect.left;
  1112.     }
  1113. if (cp->pictopen) {
  1114.     if (r < cp->xmin) cp->xmin = r;
  1115.     if (r > cp->xmax) cp->xmax = r;
  1116.     }
  1117. return(r);
  1118. }
  1119.  
  1120. short sy(short y, cnr *cp)        /* convert data stream y-coordinate to Mac coordinate */
  1121. {
  1122. register short r;
  1123.  
  1124. /* if (PictPtr == 0) {
  1125.     if ((cur_ptsize == 9) && (cur_rows == 24)) r = 139 - y;
  1126.     else r = 188 - y;
  1127.     }
  1128. else {
  1129.     if ((cur_ptsize == 9) && (cur_rows == 24)) r = 146 - y;
  1130.     else r = 195 - y;
  1131.     } */
  1132.     
  1133. r = (cp->vpixsize - 19)/2 - y;
  1134. if (cp->PictPtr == 0) {
  1135.     r += cp->textRect.top;
  1136.     }
  1137. if (cp->pictopen) {
  1138.     if (r < cp->ymin) cp->ymin = r;
  1139.     if (r > cp->ymax) cp->ymax = r;
  1140.     }
  1141. return(r);
  1142. }
  1143.  
  1144. void myLineTo(short x, short y, cnr *cp)
  1145. {
  1146. switch (cp->linet) {    /* set pen pattern for line type */
  1147.     case 8:                /* invisible */
  1148.             PenPat(&qd.white);
  1149.             break;
  1150.     default:            /* all other, until I figure out how to do this */
  1151.             PenPat(&qd.black);
  1152.             break;
  1153.     }
  1154.                     /* set pen width as requested */
  1155. if (cp->linew == 0) PenSize(1, 1);
  1156. else PenSize(cp->linew, cp->linew);
  1157. LineTo(x, y);        /* draw the line */
  1158. PenPat(&qd.black);    /* restore QuickDraw defaults */
  1159. PenSize(1, 1);
  1160. }
  1161.  
  1162. void myDrawString(unsigned char *s, cnr *cp)
  1163.                             /* s is a Pascal string */
  1164. {
  1165. short i;
  1166. unsigned char xlstr[256];    /* translated copy of string */
  1167. Point penloc;
  1168. short texttop, textleft, textbottom, textright;
  1169. FontInfo fi;
  1170.  
  1171. if (s[0] == 0) return;        /* just return if null string */
  1172. xlstr[0] = s[0];            /* copy the string */
  1173. memcpy(xlstr+1, s+1, s[0]);
  1174.  
  1175. if (cp->nl_handle != 0) {
  1176.     for (i=1; i <= xlstr[0]; i++)        /* translate EBCDIC for language */
  1177.         xlstr[i] = (cp->nltab)[xlstr[i]];
  1178.     }
  1179.  
  1180. if (cp->pictopen && (xtabh != 0)) {
  1181.     for (i=1; i <= xlstr[0]; i++)        /* translate string to ASCII */
  1182.         xlstr[i] = (*xtabh)[xlstr[i]];
  1183.     }
  1184. if (cp->pictopen) {
  1185.     GetPen(&penloc);
  1186.     textleft = penloc.h;
  1187.     GetFontInfo(&fi);
  1188.     texttop = penloc.v + fi.ascent;
  1189.     textbottom = penloc.v - fi.descent - fi.leading;
  1190.     }
  1191. DrawString(xlstr);
  1192. if (cp->pictopen) {
  1193.     GetPen(&penloc);
  1194.     textright = penloc.h;
  1195.     if (texttop > cp->ymax) cp->ymax = texttop;
  1196.     if (texttop < cp->ymin) cp->ymin = texttop;
  1197.     if (textbottom > cp->ymax) cp->ymax = textbottom;
  1198.     if (textbottom < cp->ymin) cp->ymin = textbottom;
  1199.     if (textleft < cp->xmin) cp->xmin = textleft;
  1200.     if (textleft > cp->xmax) cp->xmax = textleft;
  1201.     if (textright < cp->xmin) cp->xmin = textright;
  1202.     if (textright > cp->xmax) cp->xmax = textright;
  1203.     }
  1204. }
  1205.  
  1206.                         /* set newcolor from data stream code */
  1207. void setrgb(short *newcolor, unsigned char code, cnr *cp)
  1208. {
  1209. if ((code == 0) || (code == 16)) code = cp->dfltcolor;
  1210.  
  1211. switch(code) {
  1212.     case 1:                /* blue */
  1213.     case 9:                /* dark blue */
  1214.         (*newcolor) = RGBblue;
  1215.         break;
  1216.     case 2:                /* red */
  1217.     case 10:            /* orange */
  1218.         (*newcolor) = RGBred;
  1219.         break;
  1220.     case 3:                /* pink */
  1221.     case 11:            /* purple */
  1222.         (*newcolor) = RGBpink;
  1223.         break;
  1224.     case 4:                /* green */
  1225.     case 12:            /* dark green */
  1226.         (*newcolor) = RGBgreen;
  1227.         break;
  1228.     case 5:                /* turquoise */
  1229.     case 13:            /* dark turquoise */
  1230.         (*newcolor) = RGBturquoise;
  1231.         break;
  1232.     case 6:                /* yellow */
  1233.     case 14:            /* mustard */
  1234.         (*newcolor) = RGByellow;
  1235.         break;
  1236.     case 7:                /* neutral */
  1237.     case 15:            /* gray */
  1238.         if (cp->cs.invertbw) (*newcolor) = RGBblack;
  1239.         else (*newcolor) = RGBwhite;
  1240.         break;
  1241.     case 8:                /* background */
  1242.         if (cp->cs.invertbw) (*newcolor) = RGBwhite;
  1243.         else (*newcolor) = RGBblack;
  1244.         break;
  1245.     default:
  1246.         if (cp->cs.invertbw) (*newcolor) = RGBblack;
  1247.         else (*newcolor) = RGBwhite;
  1248.         break;
  1249.     }
  1250. }
  1251.  
  1252.                             /* convert marker code to character */
  1253. void setmark(unsigned char *mark, unsigned char code, cnr *cp)        
  1254. {
  1255. switch(code) {
  1256.     case 0x00:            /* default */
  1257.         (*mark) = cp->dfltmarker;
  1258.         break;
  1259.     case 0x01:            /* cross */
  1260.         (*mark) = 0x46;    /* sort of a cross */
  1261.         break;
  1262.     case 0x02:            /* plus */
  1263.         (*mark) = 0x4e;    /* normal plus */
  1264.         break;
  1265.     case 0x05:            /* 6-point star */
  1266.     case 0x06:            /* 8-point star */
  1267.         (*mark) = 0x5c;    /* normal asterisk */
  1268.         break;
  1269.     default:
  1270.         (*mark) = 0xb5;    /* solid diamond */
  1271.         break;
  1272.     }
  1273. }
  1274.  
  1275.                         /* define pattern from code */
  1276. void setpat(PatPtr pat, unsigned char code, cnr *cp)        
  1277. {
  1278. static Pattern pattab[16] = {
  1279.     {0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff},    /* 87.5% gray */
  1280.     {0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77},    /* 75% gray */
  1281.     {0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55},    /* 50% gray */
  1282.     {0xaa, 0x00, 0x55, 0x00, 0xaa, 0x00, 0x55, 0x00},    /* 25% gray */
  1283.     {0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00},    /* 12.5% gray */
  1284.     {0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00},    /* 6.25% gray */
  1285.     {0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00},    /* 3.125% gray */
  1286.     {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},    /* 1.5625% gray */
  1287.     {0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88},    /* vertical lines */
  1288.     {0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00},    /* horizontal lines */
  1289.     {0x11, 0x11, 0x22, 0x22, 0x44, 0x44, 0x88, 0x88},    /* "/" diags, less steep */
  1290.     {0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88},    /* "/" diags., 45 degrees */
  1291.     {0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x11, 0x11},    /* "\" diags., less steep */
  1292.     {0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11},    /* "\" diags., 45 degrees */
  1293.     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},    /* white (none) */
  1294.     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};    /* black (solid) */    
  1295.  
  1296. if (code == 0) memcpy(pat, &(cp->dfltpat), 8);
  1297. else {
  1298.     if (code > 16) code = 16;
  1299.     memcpy(pat, &(pattab[code-1]), 8);
  1300.     }
  1301. }
  1302.  
  1303. void setmixmode(short mode, cnr *cp)
  1304. {
  1305. if (mode == 0) mode = cp->dfltmix;
  1306. switch(mode) {
  1307.     case 1:                /* "mix" colors */
  1308.             if (colormac && (!cp->cs.nocolor)) {
  1309.                 if (cp->cs.invertbw) {
  1310.                     PenMode(adMin);
  1311.                     cp->copymode = adMin;
  1312.                     }
  1313.                 else {
  1314.                     PenMode(adMax);
  1315.                     cp->copymode = adMax;
  1316.                     }
  1317.                 }
  1318.             else {
  1319.                 PenMode(patOr);
  1320.                 cp->copymode = srcOr;
  1321.                 }
  1322.             break;
  1323.     default:            /* overpaint */
  1324.             PenMode(patCopy);
  1325.             cp->copymode = srcCopy;
  1326.             break;
  1327.     }
  1328. }
  1329.  
  1330. void openpictfile(cnr *cp)
  1331. {
  1332. Point where;
  1333. DlgHookProcPtr dlgHook;
  1334. SFReply reply;
  1335. OSErr rc;
  1336. short i;
  1337. long longzero = 0;
  1338. long iocount;
  1339. GrafPtr gp;
  1340.  
  1341. where = sfppoint;
  1342. dlgHook = 0;
  1343. arrowcursor();
  1344. SFPutFile(where, "\pSave graphics in:",
  1345.           cp->pict_fName, dlgHook, &reply);
  1346. if (reply.good == 0) return;
  1347. (cp->pict_fName)[0] = reply.fName[0];                /* save filename */
  1348. memcpy(cp->pict_fName+1, reply.fName+1, reply.fName[0]);
  1349. rc = FSDelete(&reply.fName, reply.vRefNum);    /* delete existing file */
  1350. if ((rc != 0) && (rc != -43)) {        /* file not found is ok */
  1351.     stoperr(wpictalrt, cp);
  1352.     return;
  1353.     }
  1354. rc = Create(&reply.fName, reply.vRefNum, 'MDRW', 'PICT');
  1355. if (rc != 0) {
  1356.     stoperr(wpictalrt, cp);
  1357.     return;
  1358.     }
  1359. rc = FSOpen(&reply.fName, reply.vRefNum, &(cp->pictfref));
  1360. if (rc != 0) {
  1361.     stoperr(wpictalrt, cp);
  1362.     return;
  1363.     }
  1364.                                 /* write 512-byte header */
  1365. for (i=0; i < 512/4; i++) {
  1366.     iocount = 4;
  1367.     rc = FSWrite(cp->pictfref, &iocount, &longzero);
  1368.     if (rc != 0) break;
  1369.     }
  1370.                                 /* write fixed fields of PICT */
  1371. if (rc == 0) {
  1372.     for (i=0; i < (sizeof(short) + sizeof(Rect))/2; i++) {
  1373.         iocount = 2;
  1374.         rc = FSWrite(cp->pictfref, &iocount, &longzero);
  1375.         if (rc != 0) break;
  1376.         }
  1377.     }
  1378.     
  1379. if (rc != 0) {                    /* clean up if write error */
  1380.     FSClose(cp->pictfref);
  1381.     FSDelete(&reply.fName, reply.vRefNum);
  1382.     stoperr(wpictalrt, cp);
  1383.     return;
  1384.     }
  1385. cp->pictvref = reply.vRefNum;
  1386. cp->pictopen = 1;
  1387. cp->picterr = 0;
  1388. cp->xmin = cp->ymin = 0x7fff;
  1389. cp->xmax = cp->ymax = 0x8000;
  1390. if (colormac && (!cp->cs.nocolor)) SetStdCProcs(&(cp->myProcs));
  1391. else SetStdProcs((QDProcs *)&(cp->myProcs));
  1392. (cp->PictPtr)->grafProcs = (QDProcs *)&(cp->myProcs);
  1393. cp->myProcs.putPicProc = (Ptr)myStdPutPic;
  1394. GetPort(&gp);
  1395. SetPort(cp->PictPtr);
  1396. TextFont(4);
  1397. cp->picthandle = 0;
  1398. cp->picthandle = OpenPicture(&(cp->PictPtr)->portRect);
  1399. ShowPen();
  1400. PicComment(picDwgBeg, 0, 0L);        /* start MacDraw Picture */
  1401. PicComment(picGrpBeg, 0, 0L);        /* begin a group */
  1402. cp->theWidth = NewHandle((Size)sizeof(Point));
  1403. if (cp->theWidth != 0) {
  1404.     ((Point *)(*(cp->theWidth)))->v = 1;
  1405.     ((Point *)(*(cp->theWidth)))->h = 3;        /* use 1/3 normal width */
  1406.     PicComment(SetLineWidth, sizeof(Point), cp->theWidth);    /* set new line width */
  1407.     }
  1408. cp->pictcount = sizeof(Picture);
  1409. SetPort(gp);
  1410. }
  1411.  
  1412. void closepictfile(cnr *cp)
  1413. {
  1414. OSErr rc;
  1415. GrafPtr gp;
  1416. long iocount, pictpos;
  1417. struct pictfixed {
  1418.     short    pictlen;
  1419.     Rect    pictrect;
  1420.     } pf;
  1421.  
  1422. GetPort(&gp);
  1423. SetPort(cp->PictPtr);
  1424. PicComment(picGrpEnd, 0, 0L);        /* end a group */
  1425. PicComment(picDwgEnd, 0, 0L);        /* end MacDraw Picture */
  1426. HidePen();
  1427. ClosePicture();
  1428. TextFont(cp->stdfont);
  1429.  
  1430. /* save the current file position */
  1431. if (cp->picterr == 0) {
  1432.     cp->picterr = GetFPos(cp->pictfref, &pictpos);
  1433.     }
  1434.     
  1435. /* set position after MacDraw header */
  1436. if (cp->picterr == 0) {
  1437.     cp->picterr = SetFPos(cp->pictfref, fsFromStart, (long)512);
  1438.     }
  1439.  
  1440. /* copy fixed picture fields */
  1441. memcpy(&pf, (Ptr)(*(cp->picthandle)), sizeof(struct pictfixed));
  1442. /* adjust rectangle to match actual plot */
  1443. pf.pictrect.top = cp->ymin;
  1444. pf.pictrect.left = cp->xmin;
  1445. pf.pictrect.bottom = cp->ymax;
  1446. pf.pictrect.right = cp->xmax;
  1447.  
  1448. /* write the final fixed picture fields */
  1449. if (cp->picterr == 0) {
  1450.     iocount = sizeof(struct pictfixed);
  1451.     cp->picterr = FSWrite(cp->pictfref, &iocount, &pf);
  1452.     }
  1453.  
  1454. /* reset the file position to the end */
  1455. if (cp->picterr == 0) {
  1456.     cp->picterr = SetFPos(cp->pictfref, fsFromStart, pictpos);
  1457.     }
  1458.     
  1459. KillPicture(cp->picthandle);
  1460. SetPort(gp);
  1461. (cp->PictPtr)->grafProcs = 0;
  1462. rc = FSClose(cp->pictfref);
  1463. if (cp->theWidth != 0) {
  1464.     DisposHandle(cp->theWidth);
  1465.     }
  1466. cp->pictopen = 0;
  1467. if ((rc != 0) || (cp->picterr != 0)) {
  1468.     stoperr(wpictalrt, cp);
  1469.     FSDelete(cp->pict_fName, cp->pictvref);
  1470.     }
  1471. }
  1472.  
  1473. pascal void myStdPutPic(Ptr dataPtr, unsigned short byteCount)
  1474. {
  1475. long iocount;
  1476.  
  1477. if (pictcp->picterr != 0) return;
  1478. iocount = byteCount;
  1479. pictcp->pictcount += byteCount;
  1480. pictcp->picterr = FSWrite(pictcp->pictfref, &iocount, dataPtr);
  1481. if (pictcp->picthandle != 0) (*(pictcp->picthandle))->picSize = pictcp->pictcount;
  1482. }
  1483.  
  1484. void hexdump(unsigned char *data, short len, cnr *cp)        /*temp*/
  1485. {
  1486. short count, i;
  1487. FILE * fp;
  1488.  
  1489. if (!cf_dblevel) return;
  1490.  
  1491. if (cp->openflg == 0) {
  1492.     fp = fopen("Ram:wsfdebug", "w");
  1493.     if (fp == 0) return;
  1494.     cp->openflg = 1;
  1495.     }
  1496. else {
  1497.     fp = fopen("Ram:wsfdebug", "a");
  1498.     if (fp == 0) return;
  1499.     }
  1500. fprintf(fp, "wsf_op = %x, wsf_gr = %x, grf_op = %x, length = %d\n",
  1501.     cp->wsfdbg.wsf_op, cp->wsfdbg.wsf_gr, cp->wsfdbg.grf_op, len);
  1502.  
  1503. count = 0;
  1504. for (i=0; i < len; i++) {
  1505.     fprintf(fp, "%02x", data[i]);
  1506.     count++;
  1507.     if (count == 32) {
  1508.         fprintf(fp, "\n");
  1509.         count = 0;
  1510.         }
  1511.     }
  1512. if (count != 0) fprintf(fp, "\n");
  1513. fprintf(fp, "\n");
  1514. fclose(fp);
  1515. }
  1516.